<template>
  <div class="container-graph">
    <div
      id="antv-x6-container"
      class="antv-x6-container"
    ></div>
    <div class="top-right">
        <!-- trigger="click"
        :open="tooltipOpen"
        @click="handleClick" -->
        <!-- :overlay-style="{ maxWidth: '500px' }" -->
      <el-tooltip
        v-model:visible="tooltipOpen"
        effect="dark"
        placement="left-start"
        trigger="click"
      >
        <template #content>
          按下ctrl+鼠标左键进行画布放大/缩小操作<br />
          按下shift+鼠标左键进行画布平移操作<br />
          滚动鼠标上下移动画布
        </template>
        <el-icon style="font-size: 30px;"><QuestionFilled /></el-icon>
      </el-tooltip>
    </div>
  </div>
</template>

<script lang="ts" setup>
import { onMounted, watch, nextTick, ref, onActivated, onDeactivated } from 'vue';
// import { message } from 'ant-design-vue';
import { Graph, Cell, Shape } from '@antv/x6';
// import { PortLayout } from '@antv/x6/lib/registry/port-layout';
import { Scroller } from '@antv/x6-plugin-scroller';
import { debounce } from 'lodash-es';
import { QuestionFilled } from "@element-plus/icons-vue";
// import { LineageRes } from '@/api/modules/lineage';

type PortPositionArgs = Array<{ position: { x: number; y: number }; angle: number }>;
interface lineageDataProps {
  tables: any[];
  lineages: any[];
}
interface Props {
  lineageData: lineageDataProps;
}

const props = withDefaults(defineProps<Props>(), {});

const LINE_HEIGHT = 24;
const NODE_WIDTH = 200;

/**
 * 根据传入的参数生成端口位置数组
 *
 * @param args - 任意类型的参数，这里预期是一个包含多个PortPositionArgs对象的数组
 * @returns 返回一个新的数组，其中每个元素都是一个对象，包含端口的位置和角度信息
 */
const erPortPosition = (args: any): any => {
  return (args as PortPositionArgs[]).map((_, index) => ({
    position: {
      x: 0,
      y: (index + 1) * LINE_HEIGHT + LINE_HEIGHT
    },
    angle: 0
  }));
};

Graph.registerPortLayout('erPortPosition', erPortPosition, true);

Graph.registerNode(
  'er-rect',
  {
    inherit: 'rect',
    markup: [
      {
        tagName: 'rect',
        selector: 'body'
      },
      {
        tagName: 'text',
        selector: 'appName'
      },
      {
        tagName: 'text',
        selector: 'tableName'
      }
    ],
    attrs: {
      rect: {
        strokeWidth: 1,
        stroke: '#5F95FF',
        fill: '#5F95FF'
      },
      appName: {
        fontWeight: 'bold',
        fill: '#ffffff',
        fontSize: 12,
        refY: 12, // 应用名垂直位置
        textWrap: {
          width: NODE_WIDTH - 20, // 减去边距
          height: 20,
          ellipsis: true
        }
      },
      tableName: {
        fontWeight: 'bold',
        fill: '#ffffff',
        fontSize: 12,
        refY: 36, // 表名垂直位置
        textWrap: {
          width: NODE_WIDTH - 20, // 减去边距
          height: 20,
          ellipsis: true
        }
      }
    },
    ports: {
      groups: {
        list: {
          markup: [
            {
              tagName: 'rect',
              selector: 'portBody'
            },
            {
              tagName: 'text',
              selector: 'portNameLabel'
            },
            {
              tagName: 'text',
              selector: 'portTypeLabel'
            }
          ],
          attrs: {
            portBody: {
              width: NODE_WIDTH,
              height: LINE_HEIGHT,
              strokeWidth: 1,
              stroke: '#5F95FF',
              fill: '#EFF4FF',
              magnet: true
            },
            portNameLabel: {
              ref: 'portBody',
              refX: 6,
              refY: '50%',
              textVerticalAnchor: 'middle',
              fontSize: 10,
              textWrap: {
                width: NODE_WIDTH / 2 - 12,
                height: 20,
                ellipsis: true
              }
            },
            portTypeLabel: {
              ref: 'portBody',
              refX: NODE_WIDTH / 2 + 6,
              refY: '50%',
              textVerticalAnchor: 'middle',
              fontSize: 10,
              textWrap: {
                width: NODE_WIDTH / 2 - 12,
                height: 20,
                ellipsis: true
              }
            }
          },
          position: 'erPortPosition'
        }
      }
    }
  },
  true
);

// 表格
const ER_RACT = {
  id: '',
  shape: 'er-rect',
  label: '',
  width: NODE_WIDTH,
  height: LINE_HEIGHT * 2,
  position: {
    x: 0,
    y: 0
  },
  ports: []
};
// 表格-label
const ER_RACT_PORTS = {
  id: '',
  group: 'list',
  attrs: {
    portNameLabel: {
      text: ''
    },
    portTypeLabel: {
      text: ''
    }
  }
};
// 线
const EDGE = {
  id: '',
  shape: 'edge',
  source: {
    cell: '1', // source-cell-id
    port: '1-1' // port-id
  },
  target: {
    cell: '2', // source-cell-id
    port: '2-1' // port-id
  },
  connector: {
    name: 'rounded',
    args: { radius: 20 }
  },
  attrs: {
    line: {
      targetMarker: 'classic',
      stroke: '#A2B1C3'
    }
  },
  zIndex: 1
};
const graphObj = ref<Graph | null>(null);
const tooltipOpen = ref(true);

/**
 * 初始化图形界面
 *
 * @async
 */
const initializeGraph = async () => {
  if (graphObj.value) {
    await graphObj.value.dispose();
    graphObj.value = null;
  }
  console.log('测试', graphObj.value);
  // console.log(1);
  const containerElement = document.getElementById('antv-x6-container');
  console.log(containerElement);
  if (!containerElement) {
    console.log('Container element not found!');
    // message.error('Container element not found!');
    return;
  }

  const graph = new Graph({
    container: containerElement,
    mousewheel: {
      enabled: true,
      minScale: 0.5,
      maxScale: 4,
      modifiers: ['ctrl']
    }, // 缩放
    background: {
      color: '#F2F7FA'
    },
    connecting: {
      allowBlank: false, // 是否允许连接到画布空白位置的点
      router: {
        name: 'er',
        args: {
          offset: 25,
          direction: 'H'
        }
      },
      createEdge() {
        return new Shape.Edge({
          connector: {
            name: 'rounded',
            args: { radius: 20 }
          },
          attrs: {
            line: {
              targetMarker: 'classic',
              stroke: '#A2B1C3'
            }
          }
        });
      }
    }
  });

  // https://x6.antv.antgroup.com/tutorial/plugins/scroller
  graph.use(
    new Scroller({
      enabled: true,
      pannable: true, // 是否启用画布平移能力（在空白位置按下鼠标后拖动平移画布）
      modifiers: 'shift', // 设置修饰键后需要点击鼠标并按下修饰键才能触发画布拖拽
      padding: {
        top: 0,
        right: 0,
        bottom: 0,
        left: 0
      }, // 设置画布四周的 padding 边距
      autoResize: true, // 是否自动扩充/缩小画布
      className: 'scrollerCss' // 附加样式名，用于定制样式
    })
  );

  const cells: Cell[] = [];

  if (props.lineageData.tables && props.lineageData.tables.length) {
    await Promise.all(
      props.lineageData.tables.map(async (item, index) => {
        const ports = await Promise.all(
          item.fieldMetadatas.map(async (port: any) => {
            return {
              ...ER_RACT_PORTS,
              id: port.id + '',
              attrs: {
                portNameLabel: {
                  text: port.fieldName
                },
                portTypeLabel: {
                  text: port.fieldNameZh
                }
              }
            };
          })
        );

        cells.push(
          graph.createNode({
            ...ER_RACT,
            id: item.id + '',
            attrs: {
              appName: {
                text: item.application.name
              },
              tableName: {
                text: `${item.tableName}${item.tableNameZh ? `【${item.tableNameZh}】` : ''}`
              }
            },
            position: {
              x: NODE_WIDTH * index + 20 * (index + 1),
              y: 20
            },
            ports
          })
        );
      })
    );
  }

  // edge
  if (props.lineageData.lineages && props.lineageData.lineages.length) {
    props.lineageData.lineages.forEach((item, index) => {
      cells.push(
        graph.createEdge({
          ...EDGE,
          id: 'edge-' + (index + 1),
          source: {
            cell: item.sourceTableId, // source-cell-id
            port: item.sourceFieldId // port-id
          },
          target: {
            cell: item.targetTableId, // source-cell-id
            port: item.targetFieldId // port-id
          }
        })
      );
    });
  }

  graph.resetCells(cells);
  graph.zoomTo(1);
  // 监听图的变化事件
  graph.on(
    'cell:changed',
    debounce(({ cell, options }) => {
      console.log('Cell changed:', cell, options);
      // 在这里可以处理最新的图数据，例如通过API发送到服务器
    }, 300)
  );

  // graph.on('node:mousedown', ({ e, node }) => {
  //   if (e.altKey) {
  //     e.stopPropagation(); // 阻止事件传播
  //   }
  // });

  graphObj.value = graph;
};

onMounted(async () => {
  await nextTick(); // 确保 DOM 已经更新
  // initializeGraph();
});

onActivated(() => {
  tooltipOpen.value = true;
});
onDeactivated(() => {
  tooltipOpen.value = false;
});

watch(
  () => props.lineageData,
  async val => {
    if (graphObj.value) {
      await graphObj.value.dispose();
      graphObj.value = null;
    }
    console.log(val);
    await nextTick(); // 确保 DOM 已经更新
    initializeGraph();
  },
  { immediate: true, deep: true }
);
</script>

<style lang="scss" scoped>
:deep(.scrollerCss) {
  overflow-x: hidden;
  overflow-y: auto;
}
.container-graph {
  width: 100%;
  height: 100%;
  position: relative;
  .antv-x6-container {
    width: 100%;
    height: 100%;
    position: relative;
  }
  .top-right {
    position: absolute;
    top: 10px;
    right: 20px;
    z-index: 99;
    font-size: 20px;
    cursor: pointer;
    :deep(.ant-tooltip) {
      max-width: 500px;
    }
  }
}
</style>
